#include "stdafx.h"
#include <fstream>
#include "crImageLoadLoader.h"

NS_CR_BEGIN

namespace image
{
	namespace loader
	{
// 		class Loader::Impl
// 		{
// 		public:
// 			Impl();
// 			~Impl();
// 
// 			Result Load();
// 			void Init(const Configuration& config);
// 
// 			void SetOption(const Url& t);
// 			void SetOption(const DefaultPath& t);
// 		private:
// 			_STD unique_ptr<cache::DiskCache>	cache_;
// 			_STD unique_ptr<thread_pool>		thread_pool_;
// 		};
// 
// 		Loader::Impl::Impl()
// 		{
// 
// 		}
// 
// 		Loader::Impl::~Impl()
// 		{
// 
// 		}
// 
// 		Result Loader::Impl::Load()
// 		{
// 			auto f = thread_pool_->commit([] {
// 				auto resp = http::Get(http::Url("http://www.baidu.com"));
// 				if (resp.error.code != http::ErrorCode::OK)
// 				{
// 					return Result();
// 				}
// 
// 				_STD ofstream o;
// 				string path;
// 				path.assign("d:\\");
// 				path.append(string::from_number(rand() % 2000000));
// 				path.append(".html");
// 				o.open(path, _STD ios::binary | _STD ios::out | _STD ios::trunc);
// 				o << resp.text;
// 				o.flush();
// 				o.close();
// 
// 				return Result( );
// 			});
// 
// 			return f.get();
// 		}
// 
// 		void Loader::Impl::Init(const Configuration& config)
// 		{
// 			thread_pool_ = _STD make_unique<thread_pool>(config.threadPoolSize);
// 		}
// 
// 		void Loader::Impl::SetOption(const Url& t)
// 		{
// 
// 		}
// 
// 		void Loader::Impl::SetOption(const DefaultPath& t)
// 		{
// 
// 		}

		//////////////////////////////////////////////////////////////////////////
		Loader::Loader()
		{
		}

		Loader::~Loader()
		{
			
		}

		void Loader::Init(const Configuration& config)
		{
			_thread_pool = _STD make_unique<thread_pool>(config.threadPoolSize);
			_cache = _STD make_unique<cache::BaseDiskCache>();
		}

		Result Loader::Run(const SpTask& task)
		{
			tstring cacheFile;
			Result result(task->_def_path().mstr());
			if ( _cache ->getCacheFile(task->_url(), _STD_FWD(cacheFile)))
			{
				result.image(cacheFile.mstr());
				task->Run(result);
				return result;
			}
			else
			{
				task->_cache_path = cacheFile;
				try
				{
					auto resp = http::Get(http::Url(task->_url().mstr()), http::Timeout(3000));
					result.status_code(resp.status_code);
 					if (resp.error)
					{
						result.error(Error((int32_t)resp.error.code, resp.error.message));
						task->Run(result);
						return result;
					}
					else
					{
						if (resp.status_code != 200 && resp.status_code != 0)
						{
							result.error(Error((int32_t)ErrorCode::EMPTY_RESPONSE, "http status error"));
						}
						else 
						{
							if (_cache->save(task->_url(), resp.text))
							{
								result.image(task->_cache_path().mstr());
							}
							else
							{
								result.error(Error((int32_t)ErrorCode::CANNOT_OPEN_OUT_FILE, "cannot open cache file"));
							}
						}
						

						task->Run(result);
						return result;
					}
				}
				catch (const std::exception& e)
				{
					crDebugf(e.what());

					result.error(Error((int32_t)ErrorCode::INTERNAL_ERROR, e.what()));
					task->Run(result);
					return result;
				}
			}

			
		}

		Result Loader::Load(SpTask&& task)
		{
			auto f = _thread_pool->commit(_STD bind(&Loader::Run, this, _STD_FWD(task)));
			return f.get();
		}

		_STD future<Result> Loader::LoadAsync(SpTask&& task)
		{
			return _thread_pool->commit(_STD bind(&Loader::Run, this, _STD_FWD(task)));
		}

		void Loader::Term()
		{
			_thread_pool->terminate();
		}

		uint32_t Loader::getTasksCount() const
		{
			return _thread_pool->getTasksCount();
		}

		uint32_t Loader::getQueuesCount() const
		{
			return _thread_pool->getQueuesCount();
		}

	}
}

NS_CR_END